from coin.strategy.interval.profile.profile import Profile, AlphaGroup
from coin.strategy.interval.model import Alpha, Transform, AlphaTrans
from coin.strategy.interval.transforms import identity, logistic_normalize

from coin.strategy.interval.alphas.taekwon import *
from functools import partial


def call_partial(my_func, **kwargs):
  ret_func = partial(my_func, **kwargs)
  ret_func.__name__ = my_func.__name__
  # ret_func.__doc__ = my_func.__doc__.format(**kwargs)
  ret_func.__doc__ = 'sung'
  return ret_func


def test(products):
  # alpha1 = Alpha(new_vwap_ma_diff, {'products': products, 'x_itv': 1})
  # alpha2 = Alpha(new_vwap_ma_diff, {'products': products, 'x_itv': 3})
  # alpha3 = Alpha(new_vwap_ma_diff, {'products': products, 'x_itv': 5})
  # alpha4 = Alpha(new_vwap_ma_diff, {'products': products, 'x_itv': 10})
  # alpha5 = Alpha(new_vwap_ma_diff, {'products': products, 'x_itv': 30})
  # alpha6 = Alpha(new_vwap_ma_diff, {'products': products, 'x_itv': 60})
  trans1 = Transform(logistic_normalize, {'factor': 2.0})
  # trans1 = Transform(identity, {'offset': 0})
  alpha_trans_lst = [
      AlphaTrans(Alpha(new_cross_vwap, {
          'products': products, 'x_itv_s': 1, 'x_itv_l': 10
      }),
                 Transform(logistic_normalize, {'factor': 3}))
  ]
  return alpha_trans_lst


def greats(products):
  ##################################################
  AlphaGroup(
      'taekwon',
      ['bitflyer-fxbtcjpy', 'bitmex-xbtusd'],
      [
          call_partial(vwap_div_mid_p, x_itv=5),  # done
          call_partial(self_volume_sq_diff, roll_itv=10),
          call_partial(cross_volume_sq_diff, roll_itv=10),
          call_partial(vwap_ma_diff, x_itv=1, roll_itv=30),
          call_partial(self_mid_vwap, x_itv=5, roll_itv=300),  # done
          call_partial(cross_vwap, x_itv_s=1, x_itv_l=10),  # done
          call_partial(buy_sell_trade_pq_diff, is_cross=True, x_itv=10),  # done
          call_partial(buy_sell_trade_pq_diff, is_cross=False, x_itv=10),  # done
          call_partial(buy_sell_trade_q_diff, is_cross=True, x_itv=10),  # done
          call_partial(buy_sell_trade_q_diff, is_cross=False, x_itv=10),  # done
          call_partial(mid_p_rev, x_itv=1),  # done
          call_partial(high_close_low, x_itv=1),  # done
          call_partial(vwap_close, x_itv=2),  # done
          call_partial(high_avg, x_itv=20),
          call_partial(low_avg, x_itv=30),
      ])
  ######################################################
  alpha_trans_lst = [
      AlphaTrans(Alpha(new_self_mid_p_rev, {
          'products': products, 'x_itv': 1
      }),
                 Transform(logistic_normalize, {'factor': 0.5})),
      AlphaTrans(Alpha(new_self_high_close_low, {
          'products': products, 'x_itv': 1
      }),
                 Transform(logistic_normalize, {'factor': 0.3})),
      AlphaTrans(Alpha(new_self_vwap_close, {
          'products': products, 'x_itv': 2
      }),
                 Transform(logistic_normalize, {'factor': 2000})),
      AlphaTrans(Alpha(new_self_buy_sell_trade_pq_diff, {
          'products': products, 'x_itv': 10
      }),
                 Transform(logistic_normalize, {'factor': 1e-5})),
      AlphaTrans(Alpha(new_self_buy_sell_trade_q_diff, {
          'products': products, 'x_itv': 10
      }),
                 Transform(logistic_normalize, {'factor': 1e-1})),
      AlphaTrans(Alpha(new_self_mid_vwap, {
          'products': products, 'x_itv': 5
      }),
                 Transform(logistic_normalize, {'factor': 0.7})),
      AlphaTrans(Alpha(new_cross_vwap, {
          'products': products, 'x_itv_s': 1, 'x_itv_l': 10
      }),
                 Transform(logistic_normalize, {'factor': 3})),
      AlphaTrans(Alpha(new_cross_buy_sell_trade_pq_diff, {
          'products': products, 'x_itv': 10
      }),
                 Transform(logistic_normalize, {'factor': 1e-6})),
      AlphaTrans(Alpha(new_cross_vwap_div_mid_p, {
          'products': products, 'x_itv': 5
      }),
                 Transform(logistic_normalize, {'factor': 150})),
      AlphaTrans(Alpha(new_cross_buy_sell_trade_q_diff, {
          'products': products, 'x_itv': 10
      }),
                 Transform(logistic_normalize, {'factor': 1e-2})),
      AlphaTrans(Alpha(new_self_vwap_ma_diff, {
          'products': products, 'x_itv': 30
      }),
                 Transform(logistic_normalize, {'factor': 3.0}))
  ]
  return alpha_trans_lst


def bitflyer_model(products):
  self_product = products[0]
  assert self_product == 'bitflyer-fxbtcjpy'
  self_alpha_trans = [
      AlphaTrans(Alpha(new_self_mid_p_rev, {
          'products': [self_product], 'x_itv': 1
      }),
                 Transform(logistic_normalize, {'factor': 0.5})),
      AlphaTrans(Alpha(new_self_high_close_low, {
          'products': [self_product], 'x_itv': 1
      }),
                 Transform(logistic_normalize, {'factor': 0.3})),
      AlphaTrans(Alpha(new_self_vwap_close, {
          'products': [self_product], 'x_itv': 2
      }),
                 Transform(logistic_normalize, {'factor': 2000})),
      AlphaTrans(Alpha(new_self_buy_sell_trade_pq_diff, {
          'products': [self_product], 'x_itv': 10
      }),
                 Transform(logistic_normalize, {'factor': 1e-5})),
      AlphaTrans(Alpha(new_self_buy_sell_trade_q_diff, {
          'products': [self_product], 'x_itv': 10
      }),
                 Transform(logistic_normalize, {'factor': 1e-1})),
      AlphaTrans(Alpha(new_self_mid_vwap, {
          'products': [self_product], 'x_itv': 5
      }),
                 Transform(logistic_normalize, {'factor': 0.7})),
  ]
  ref_products = products[1:]
  cross_alpha_trans = list()
  for ref_product in ref_products:
    cross_products = [self_product, ref_product]
    cross_alpha_trans = cross_alpha_trans + [
        AlphaTrans(Alpha(new_cross_vwap, {
            'products': cross_products, 'x_itv_s': 1, 'x_itv_l': 10
        }),
                   Transform(logistic_normalize, {'factor': 3})),
        AlphaTrans(
            Alpha(new_cross_buy_sell_trade_pq_diff, {
                'products': cross_products, 'x_itv': 10
            }),
            Transform(logistic_normalize, {'factor': 1e-6})),
        AlphaTrans(Alpha(new_cross_vwap_div_mid_p, {
            'products': cross_products, 'x_itv': 5
        }),
                   Transform(logistic_normalize, {'factor': 150})),
        AlphaTrans(
            Alpha(new_cross_buy_sell_trade_q_diff, {
                'products': cross_products, 'x_itv': 10
            }),
            Transform(logistic_normalize, {'factor': 1e-2})),
        AlphaTrans(Alpha(new_self_vwap_ma_diff, {
            'products': cross_products, 'x_itv': 30
        }),
                   Transform(logistic_normalize, {'factor': 3.0}))
    ]
  return self_alpha_trans + cross_alpha_trans


def merge_greats(base_product, ref_products=[]):
  self_alpha = AlphaGroup(
      'self',
      [base_product],
      [
          call_partial(self_volume_sq_diff, roll_itv=10),
          call_partial(self_mid_vwap, x_itv=5, roll_itv=300),
          call_partial(buy_sell_trade_pq_diff, is_cross=False, x_itv=10),
          call_partial(buy_sell_trade_q_diff, is_cross=False, x_itv=10),
          call_partial(mid_p_rev, x_itv=1),
          call_partial(high_close_low, x_itv=1),
          # call_partial(high_low_vwap, x_itv=1),
          call_partial(vwap_close, x_itv=2),
          call_partial(high_avg, x_itv=20),
          call_partial(low_avg, x_itv=30),
      ])
  cross_alpha_func = [
      call_partial(cross_vwap, x_itv_s=1, x_itv_l=10),
      call_partial(vwap_div_mid_p, x_itv=5),
      call_partial(vwap_ma_diff, x_itv=1, roll_itv=30),
      call_partial(cross_volume_sq_diff, roll_itv=10),
      call_partial(buy_sell_trade_pq_diff, is_cross=True, x_itv=10),
      call_partial(buy_sell_trade_q_diff, is_cross=True, x_itv=10),
  ]
  # products = ['bitmex-xbtusd', 'okex-btcusd-quarter', 'okex-btcusd-perpetual']
  cross_alpha = [
      AlphaGroup('cross', [base_product, ref_product], cross_alpha_func)
      for ref_product in ref_products
  ]
  return [self_alpha] + cross_alpha
